package com.magist.core.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.magist.core.constants.Deleted;
import com.magist.core.dao.BaseMapper;
import com.magist.core.entity.BaseEntity;
import com.magist.core.entity.CxtHolder;
import com.magist.core.entity.Page;
import com.magist.core.util.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Random;

public abstract class SimpleServiceImpl<T extends BaseEntity> implements BaseService<T> {

    /**
     * 泛型注入
     */
    @Autowired
    protected BaseMapper<T> mapper;

    @Override
    public List<T> find(T entity) {
        Example example = new Example(entity.getClass());
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("deleted", "F");
        if (StringUtils.isNotEmpty(entity.getId())) {
            criteria.andEqualTo("id", entity.getId());
        }
        if (entity.getCreateById() != null) {
            criteria.andEqualTo("createById", entity.getCreateById());
        }
        if (entity.getModifyById() != null) {
            criteria.andEqualTo("modifyById", entity.getModifyById());
        }
        Field[] fields = entity.getClass().getDeclaredFields();
        for (Field field : fields) {
            Type type = field.getGenericType();
            if (type.getTypeName().equals("java.lang.String") && (field.getModifiers() == 2)) {
                field.setAccessible(true);
                try {
                    if (field.get(entity) != null && field.get(entity).toString().length() > 0) {
                        String value = field.get(entity).toString().trim();
                        if (value.startsWith("%") || value.endsWith("%"))
                            criteria.andLike(field.getName(), value);
                        else
                            criteria.andEqualTo(field.getName(), value);
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            } else if (Date.class.getName().equals(type.getTypeName()) && (field.getModifiers() == 2)) {
                field.setAccessible(true);
                try {
                    if (field.get(entity) != null && field.get(entity).toString().length() > 0) {
                        Object value = field.get(entity);
                        criteria.andEqualTo(field.getName(), value);
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
        return find(example);
    }

    @Override
    public PageInfo<T> page(T entity, Page page) {
        PageHelper.startPage(page.getCurrPage(), page.getLimit());
        List<T> list = this.find(entity);
        PageInfo<T> pageInfo = new PageInfo(list);
        return pageInfo;
    }

    @Override
    public void insert(Collection<T> entities) {
        for (T ti : entities) {
            this.insert(ti);
        }
    }

    @Override
    public void update(Collection<T> entities) {
        for (T ti : entities) {
            this.update(ti);
        }
    }

    @Override
    public int insert(T entity) {
        Date now = new Date();
        entity.setModifyTime(now);
        entity.setCreateTime(now);
        if (CxtHolder.getUser() != null) {
            entity.setCreateById(CxtHolder.getUser().getUserId());
            entity.setModifyById(CxtHolder.getUser().getUserId());
        }
        return mapper.insert(entity);
    }

    @Override
    public int delete(T entity) {
        entity.setDeleted(Deleted.YES_STR);
        return this.update(entity);
    }

    @Override
    public int update(T entity) {
        Date now = new Date();
        if (CxtHolder.getUser() != null) {
            entity.setModifyById(CxtHolder.getUser().getUserId());
        }
        entity.setModifyTime(now);
        int result = mapper.updateByPrimaryKeySelective(entity);

        return result;
    }

    @Override
    public T getById(String id) {
        Example example = new Example((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("id", id);
        criteria.andEqualTo("deleted", Deleted.NO_STR);
        List<T> list = mapper.selectByExample(example);
        if (list.isEmpty()) {
            return null;
        } else {
            return list.get(0);
        }

    }

    @Override
    public List<T> find(Example example) {
        return mapper.selectByExample(example);
    }

    @Override
    public T findSingle(T entity) {
        List<T> ls = this.find(entity);
        if (ls.size() > 0)
            return ls.get(0);
        return null;
    }

    @Override
    public T findLast(T entity) {
        List<T> list = mapper.select(entity);
        if (!CollectionUtils.isEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 生成id yyMMdd+seq(8)+rand(3)
     */
    @Override
    public String getNewId(Long step) {
        Long id = mapper.getNewId(step);
        String no = DateUtil.format(new Date(), "yyMMdd");
        no = no + String.format("%08d", id % 100000000);
        Random r = new Random();
        no = no + String.format("%03d", r.nextInt(999));
        return no;
    }

    @Override
    public String getNewId() {
        return this.getNewId(1L);
    }

}
